#include <winsock2.h>
#include <ws2tcpip.h>

#include <windows.h>
#include <stdio.h>
#include <conio.h>

#include "wd-dask64.h"
#include "wddaskex.h"
#include <string.h> // 包含memset函数


#include <stdlib.h>
#pragma comment(lib, "Ws2_32.lib")

#define PORT 5008
//#define IP "0.0.0.0"
#define IP "192.168.250.133"
//#define IP "192.168.250.206"
#define BUFFER_SIZE 256

U16 channel;
U16 range;
char* file_name_base = "dbfai"; // 文件名基础部分
U32 read_count = 2100000;
U32 samp_intrv = 200;//采样频率 = 1M;  采样频率 = 主频200MHz/samp_intrv 

#define DATA_SIZE 2100000 
unsigned short ai_buf[DATA_SIZE];
unsigned short ai_buf2[DATA_SIZE];
DAS_IOT_DEV_PROP cardProp;
U16 chcnt;
I16 card = 0;

char dianxinID[BUFFER_SIZE];
char dianxinID_last[BUFFER_SIZE];
// 服务器线程函数
DWORD WINAPI server_thread(LPVOID lpParam) {
    WSADATA wsaData;
    SOCKET server, conn;
    struct sockaddr_in server_addr, client_addr;
    int client_addr_len = sizeof(client_addr);
    char buffer[BUFFER_SIZE];
    char bytes_received;
    char client_ip_str[INET_ADDRSTRLEN];

    // 初始化Winsock
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        fprintf(stderr, "WSAStartup failed\n");
        return 1;
    }

    // 创建套接字
    server = socket(AF_INET, SOCK_STREAM, 0);
    if (server == INVALID_SOCKET) {
        fprintf(stderr, "socket failed\n");
        WSACleanup();
        return 1;
    }

    // 设置套接字选项
    int opt = 1;
    setsockopt(server, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));

    // 绑定IP地址和端口
    server_addr.sin_family = AF_INET;
    inet_pton(AF_INET, IP, &server_addr.sin_addr);
    server_addr.sin_port = htons(PORT);
    if (bind(server, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        fprintf(stderr, "bind failed, error code: %d\n", WSAGetLastError());

        closesocket(server);
        WSACleanup();
        return 1;
    }

    // 监听连接
    listen(server, 5);
    printf("\n");
    printf("服务器启动，等待客户端连接...\n");
    printf("\n");
    // 接受连接
    while (1) {
        conn = accept(server, (struct sockaddr*)&client_addr, &client_addr_len);
        if (conn == INVALID_SOCKET) {
            fprintf(stderr, "accept failed\n");
            continue;
        }
        inet_ntop(AF_INET, &client_addr.sin_addr, client_ip_str, sizeof(client_ip_str));
        printf("\n");
        printf("客户端连接成功，IP地址: %s\n", client_ip_str);

        while (1) {
            bytes_received = recv(conn, buffer, sizeof(buffer), 0);
            if (bytes_received <= 0) {
                fprintf(stderr, "recv failed or connection closed\n");
                break;
            }
            /*    printf("\n");
                printf("接收到的数据: ");*/
                /*for (int i = 0; i < bytes_received; ++i) {
                    printf("%02x ", (unsigned char)buffer[i]);
                }*/
                //printf("\n");
                //保存上一次电芯码
            memcpy(dianxinID_last, dianxinID, sizeof(dianxinID));
            // 复制电芯ID码数组
            memcpy(dianxinID, buffer, sizeof(buffer));
            //printf(dianxinID);
        }

        closesocket(conn);
    }

    // 关闭套接字
    closesocket(server);
    WSACleanup();
    return 0;
}

void main()
{
    I16 err, card_num, Id;
    BOOLEAN halfReady, fStop;
    U32 count = 0, count1, startPos;
    U16 card_type = 1;
    int file_index = 0; // 文件索引，用于生成不同的文件名

    // 创建线程运行服务器代码
    HANDLE hThread = CreateThread(NULL, 0, server_thread, NULL, 0, NULL);
    if (hThread == NULL) {
        fprintf(stderr, "CreateThread failed\n");
        return 1;
    }
    // 关闭线程句柄
    CloseHandle(hThread);

    printf("This program inputs data from all channels by\ndouble-buffer mode, and store data to different CSV files. The size of circular\nbuffer is %d.\n",
        read_count);
    card_type = WD_ChooseDeviceType(0);
    printf("Please input a card number: ");
    scanf(" %hd", &card_num);
    if ((card = WD_Register_Card(card_type, card_num)) < 0) {
        printf("Register_Card error=%d\n", card);
        exit(1);
    }
    //获取采集卡属性
    WD_GetDeviceProperties(card, 0, &cardProp);
    range = cardProp.default_range;
    chcnt = cardProp.num_of_channel;
    channel = chcnt - 1;
    WD_AI_CH_Config(card, -1, range);
    // 配置采集卡的模拟输入通道的采样时间基准等参数
    err = WD_AI_Config(card, WD_IntTimeBase, 1, WD_AI_ADCONVSRC_TimePacer, 0, 1);
    if (err != 0) {
        // 如果配置失败，打印错误码并退出程序
        printf("WD_AI_Config error=%d", err);
        exit(1);
    }

    while (1)
    {
        /*printf("Please input a dianxinID: ");
        scanf(" %hd", &dianxinID);*/
        if (strcmp(dianxinID, dianxinID_last) != 0)
        {
            //保存上一次电芯码
            memcpy(dianxinID_last, dianxinID, sizeof(dianxinID));
            //// 使用memset清零数组
       //memset(ai_buf, 0, sizeof(ai_buf));
       //memset(ai_buf2, 0, sizeof(ai_buf2));
       // 配置采集卡的触发模式、触发源等参数 WD_AI_TRGMOD_POST  WD_AI_TRGMOD_MIDL
            err = WD_AI_Trig_Config(card, WD_AI_TRGMOD_MIDL, WD_AI_TRGSRC_ANA, WD_AI_TrgNegative, 0, 0.06, 1030000, 1070000, 0, 1);//WD_AI_TRGSRC_ANA模拟量触发，0.01触发
            if (err != 0) {
                // 如果配置失败，打印错误码并退出程序
                printf("WD_AI_Trig_Config error=%d", err);
                exit(1);
            }
            // 设置采集卡的异步双缓冲模式
            err = WD_AI_AsyncDblBufferMode(card, 1);
            if (err != 0) {
                // 如果设置失败，打印错误码并退出程序
                printf("DAQ2K_AI_DblBufferMode error=%d", err);
                exit(1);
            }
            // 设置连续采集的第一个缓冲区
            err = WD_AI_ContBufferSetup(card, ai_buf, read_count, &Id);//read_count为8的倍数  &Id：Returns the index of the currently set up buffer
            if (err != 0) {
                // 如果设置失败，打印错误码并退出程序
                printf("WD_AI_ContBufferSetup error=%d for the 1st buffer", err);
                exit(1);
            }
            // 设置连续采集的第二个缓冲区
            WD_AI_ContBufferSetup(card, ai_buf2, read_count, &Id);
            if (err != 0) {
                // 如果设置失败，打印错误码并退出程序
                printf("WD_AI_ContBufferSetup error=%d for the 2nd buffer", err);
                exit(1);
            }
            // 提示用户程序不会停止，直到按下任意键
            printf("It will not stop until you press a key.\n\nPress any key to start the operation.\n");

            // 生成文件名
            //char file_name[BUFFER_SIZE];

            //sprintf(file_name, "%s%s_%d", file_name_base, dianxinID, file_index);
            //
            //printf(file_name);
            // 开始连续采集通道数据并保存到文件，使用异步操作
            err = WD_AI_ContScanChannelsToFile(card, channel, Id, dianxinID, read_count / chcnt, samp_intrv, samp_intrv, ASYNCH_OP);
            if (err != 0) {
                // 如果采集失败，打印错误码并退出程序
                printf("WD_AI_ContScanChannels error=%d", err);
                exit(1);
            }
            // 提示用户按下任意键停止输入操作，并打印数据计数
            printf("\n\nPress any key to stop input operation.");
            printf("\n\nData count : \n");
            do {
                WD_AI_AsyncDblBufferHalfReady(card, &halfReady, &fStop);
            } while (!halfReady);//新buffer准备好则跳出循环
            WD_AI_AsyncDblBufferToFile(card);//将循环缓冲区中数据保存到磁盘文件中

            char file_name_csv[BUFFER_SIZE];
            //const char* filename1 = "iv_data.csv";
            sprintf(file_name_csv, " %s.csv", dianxinID);
            // 打开CSV文件
            FILE* fp = fopen(file_name_csv, "w");
            if (fp == NULL) {
                perror("无法打开文件");
                return EXIT_FAILURE;
            }

            // 写入CSV表头
            fprintf(fp, "Current,Voltage\n");

            // 处理数据并写入CSV文件
            for (int i = 0; i < DATA_SIZE; i += 2) {
                // 确保有完整的一对数据
                if (i + 1 < DATA_SIZE) {
                    // 处理电流值
                    int current = ai_buf[i];
                    if (current > 40000) {
                        current -= 65535; // 处理大于40000的值
                    }
                    current *= 1; // 乘以1

                    // 处理电压值
                    int voltage = ai_buf[i + 1];
                    if (voltage > 40000) {
                        voltage -= 65535; // 处理大于40000的值
                    }
                    voltage *= 1; // 乘以1

                    // 写入处理后的值
                    fprintf(fp, "%d,%d\n", current, voltage);
                }

            }
            // 关闭文件
            fclose(fp);

            printf("数据已成功保存到 %s\n", file_name_csv);
            printf("共写入 %d 对电流-电压值\n", DATA_SIZE / 2);

            count += (read_count);

            file_index++; // 更新文件索引
            WD_AI_AsyncClear(card, &startPos, &count1);//停止异步操作

            if (kbhit()) // 如果用户按下任意键，退出循环 || file_index == 2
            {
                break;
            }

        }

    }
    count += (count1);
    WD_Release_Card(card);
    printf("\n\n%d input data are stored in different CSV files.\n", count);
    printf("\nPress ENTER to exit the program. "); getch();
}
